<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../js/vue.global.js"></script>
</head>
<body>
    <div id="app">
        <h3>{{msg}}</h3>
        <p ref="p">{{count}}</p>
        <p >{{count}}---{{doubleCount}}</p>
        <p><button @click="addCount">点击count++</button></p>
        <hr>
        <p><input ref="userInp" type="text" v-model="info.user">{{info.user}}</p>
        <p><input type="text" v-model="info.pwd">{{info.pwd}}</p>
        <p>{{info.user}}----{{info.pwd}}-----{{info.height}}</p>


    </div>
</body>

<!-- <script>
    // Vue3  => 选项式API

    console.log(Vue);

    var {createApp} = Vue;


    // createApp创建实例(应用)的方法 => 可以接收options选项配置 => 返回创建实例(应用)

    // 声明式渲染
    var app = createApp({
        data(){
            return {
                msg:"hello world",
                count:1,
            }
        },
        methods:{
            addCount(){
                this.count++;
            }
        },
        computed:{
            doubleCount(){
                return this.count * 2
            },
            tripleCount(){
                return this.count * 3
            }
        },
        watch:{
            count(newVal,oldVal){
                console.log("count改变了",newVal,oldVal);
            }
        },
        mounted(){
            // this ->代理对象(需要通过代理对象来访问数据/方法)
            console.log(this);
        }
    })

    console.log(app);
    app.mount("#app");



</script> -->

<script>
    console.dir(Vue);  // 打印一个对象的属性和方法 
    var {createApp} = Vue;

   

    var app = createApp({
        // data(){},

        // 选项式写法  -> this指向 Proxy对象(依赖于代理对象进行取值和赋值)
        // computed:{},
        // methods: {},
        // watch:{}

        // 组合式  -> 原理(闭包)
        setup(props) {  // props组件通信时用于接收数据的方法之一

            let {ref,reactive,readonly,computed,watch,watchEffect,nextTick} = Vue;

            // ref => 一般用于值类型(也可以用于引用数据类型) => 接受一个内部值，返回一个响应式的、可更改的 ref 对象,此对象只有一个指向其内部值的属性 .value。

            let msg = ref("hello world");  
            console.log(msg);
            // console.log(msg.value);
            // msg.value = "hello Vue";

            let count = ref(0);
            console.log(count);

            // reactive  一般用于引用类型 返回一个对象的响应式代理(proxy对象)
            let info = ref({
                user:"a123123",
                pwd:"123123",
            })
            info.height = "175cm";
            // console.log(info);
            // console.log(info.user);
            // console.log(info.pwd);

            // let obj = readonly({
            //     user:"a123123",
            //     pwd:"123123",
            // })
            // obj.user="b123123";
            // console.log(obj);
            // console.log(obj.user);
            // console.log(obj.pwd);


            // 方法  
            let addCount = ()=>{
                count.value++
            }

            // 计算属性   接受一个 getter 函数，返回一个只读的响应式 ref 对象。该 ref 通过 .value 暴露 getter 函数的返回值。它也可以接受一个带有 get 和 set 函数的对象来创建一个可写的 ref 对象。
            // let doubleCount = computed(()=>{  //默认只有取值
            //     return count.value * 2;
            // })

            let doubleCount = computed({
                get(){
                    return count.value * 2;
                },
                set(val){
                    count.value = val / 2;
                }
            })

            // doubleCount.value = 4;
            // console.log("doubleCount",doubleCount);

            // watch   侦听一个或多个响应式数据源，并在数据源变化时调用所给的回调函数。

            // watch(watchData,callback,config)
            // watchData  监听的数据  (ref对象 proxy对象 函数(计算属性)  数据)
            // callback   数据改变时执行的回调函数
            // config    监听的额外配置 
            // config配置
            //          immediate：在侦听器创建时立即触发回调。第一次调用时旧值是 undefined。
            //          deep：如果源是对象，强制深度遍历，以便在深层级变更时触发回调。参考深层侦听器。
            //          flush：调整回调函数的刷新时机。参考回调的刷新时机及 watchEffect()。 

            // 监听ref对象  newVal,oldVal(返回的ref.value值)
            // watch(count,(newVal,oldVal)=>{
            //     console.log("count发生改变",newVal,oldVal);
            // })

            // ref()和reactive() 默认都使用的是深度监听
            // 监听Proxy对象  newVal,oldVal(返回的Proxy对象本身)
            // watch(info,(newVal,oldVal)=>{
            //     console.log("info发生改变",newVal,oldVal);
            // })

           
            // watch接收一个函数  => 现根据原函数得到一个计算属性,再监听该计算属性的变化
            // watch(()=>info.user,(newVal,oldVal)=>{
            //     console.log("info发生改变",newVal,oldVal);
            // })

            // var user = computed(()=>{
            //     return info.user;
            // })
            // console.log(user);
            // watch(user,(newVal,oldVal)=>{
            //     console.log("user发生改变",newVal,oldVal);
            // })

            // 监听多个    
            // watch([msg,count],([msgNewVal,countNewVal],[msgOldVal,countOldVal])=>{
            //     console.log("msg改变",msgNewVal,msgOldVal);
            //     console.log("count改变",countNewVal,countOldVal);
            // })
         
            
            let userInp = ref();
            watch([()=>info.user,()=>info.pwd],([userNewVal,NewVal],[userOldVal,OldVal])=>{
                console.log("user改变",userNewVal,userOldVal);
                console.log("pwd改变",NewVal,OldVal);
                
                console.log("userInp",userInp);
                console.log("userInp",userInp.value.value);
            })


            // 立即运行一个函数，同时响应式地追踪其依赖，并在依赖更改时重新执行。  => 1. 立即执行  2. 依赖改变时才执行

            // 默认情况下，用户创建的侦听器回调，都会在 Vue 组件更新之前被调用。这意味着你在侦听器回调中访问的 DOM 将是被 Vue 更新之前的状态。

            // var p = ref();
            // watchEffect(()=>{
            //     console.log("数据发生改变:count",count.value);
            //     console.log("数据发生改变:p",p.value); // undefined
            //     nextTick(()=>{  //在视图更新之后在获取
            //         console.log("数据发生改变:p",p.value);
            //     })
            // })


            var p = ref();
            watchEffect(()=>{
                console.log("数据发生改变:count",count.value);
                console.log("数据发生改变:p",p.value); // undefined
               
            },{flush:"post"})

            // watchEffect(()=>{
            //     console.log("数据发生改变",doubleCount.value);
            // })
            // watchEffect(()=>{
            //     console.log("数据发生改变",info.user);
            // })


            // watchEffect(()=>{
            //     try{
            //         searchGoodsPI({
            //             wd:"",
            //             col:"price",
            //             type:"asc"
            //         })
            //     }
            // })

           




       



           





       





            return {
                msg,
                count,
                info,
                addCount,
                doubleCount,
                userInp,
                p
            }
            
        }



    });


    app.mount("#app");



</script>

</html>